package com.tidc.manage.tool;

import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * Description:
 * 基于POI封装的导表工具
 * 用于只对任意一种数据格式导入Excel表的数据导入工具
 * TODO 基本上可以使用，但是需要细节完善。
 *
 * @author zcolder
 * @date 2018-10-19
 */
@Deprecated
public class SheetDataUtil<T> {
    /**
     * 用于自增的行号
     */
    private int lineNumber;

    /**
     * 自定义每列的标题
     */
    private ArrayList<String> customHeaders;

    /**
     * 默认每列的标题为属性名
     */
    private ArrayList<String> defaultHeaders;

    /**
     * 表对象
     */
    private Sheet sheet;

    /**
     * 用于标记是否存在自定义每列的标题
     */
    private boolean isExistHeaders;

    /**
     * 数据
     */
    private Collection<T> data;

    /**
     * 泛型T对象的所有属性的Getter方法
     */
    private ArrayList<String> getterMethodNames = new ArrayList<>();

    /**
     * 需要忽略的字段
     */
    private ArrayList<String> ignoredFields;

    /**
     * 存在要忽略的字段
     */
    private boolean isExistIgnoredFields;

    /**
     * 行 对象
     */
    private Row row;

    public SheetDataUtil(Sheet sheet) {
        this.sheet = sheet;
    }

    public SheetDataUtil<T> setData(Collection<T> data) {
        this.data = data;
        return this;
    }

    public SheetDataUtil<T> setHeaders(String... headers) {
        this.customHeaders = new ArrayList<>(Arrays.asList(headers));
        this.isExistHeaders = true;
        return this;
    }

    public SheetDataUtil<T> setIgnoredFields(String... fieldName) {
        this.ignoredFields = new ArrayList<>(Arrays.asList(fieldName));
        this.isExistIgnoredFields = true;
        return this;
    }

    public void exportData() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 通过过反射获取所有字段，并组装Getter方法名
        setGetterMethodNames(data.iterator().next().getClass());
        // 导入每列的标题，如果用户有自定义
        importHeaders();
        // 循环将数据填充入excel表
        for (T t : data) {
            row = sheet.createRow(lineNumber++);
            int i = 0;
            for (String getterMethodName : getterMethodNames) {
                // 通过获取get方法，来获取实例的属性值
                Method getterMethod = t.getClass().getMethod(getterMethodName);
                Object value = getterMethod.invoke(t);
                // 此处的判断顺序 按照类型的使用概率
                if (value instanceof Number) {
                    if (value instanceof Integer) {
                        row.createCell(i).setCellValue((Integer) value);
                    } else if (value instanceof Long) {
                        row.createCell(i).setCellValue((Long) value);
                    } else if (value instanceof Float) {
                        row.createCell(i).setCellValue((Float) value);
                    } else if (value instanceof Double) {
                        row.createCell(i).setCellValue((Double) value);
                    } else if (value instanceof Byte) {
                        row.createCell(i).setCellValue((Byte) value);
                    } else if (value instanceof Short) {
                        row.createCell(i).setCellValue((Short) value);
                    }
                }
                // 除了数字类型之外，其他都转为文本
                row.createCell(i).setCellValue(value.toString());
                i++;
            }
        }
    }

    private void importHeaders() {
        ArrayList<String> headers = isExistHeaders ? customHeaders : defaultHeaders;
        row = sheet.createRow(lineNumber++);
        for (int i = 0; i < headers.size(); i++) {
            row.createCell(i).setCellValue(headers.get(i));
        }
    }

    private void setGetterMethodNames(Class clazz) {
        defaultHeaders = new ArrayList<>();
        for (Field field : clazz.getDeclaredFields()) {
            String fieldName = field.getName();
            // 忽略不需要的字段
            if (isExistIgnoredFields && ignoredFields.contains(fieldName)) {
                continue;
            }
            getterMethodNames.add("get"
                    + fieldName.substring(0, 1).toUpperCase()
                    + fieldName.substring(1));
            defaultHeaders.add(fieldName);
        }
    }
}
